/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.planning.tactical.wizard.spray;

import java.awt.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import nl.cloudfarming.client.model.CropProtection;
import nl.cloudfarming.client.model.CropProtectionTask;
import nl.cloudfarming.client.model.Operation;
import nl.cloudfarming.client.model.ProductionUnit;
import org.netbeans.validation.api.Problems;
import org.netbeans.validation.api.ui.ValidationListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.Utilities;

/**
 * Controller of the OperationPanel
 * @author Merijn Zengers
 */
public class OperationController extends ValidationListener implements WizardDescriptor.Panel {

    public static final String CROP_PROTECTION_TASK_PROPERTIES = "pesicideProperties";
    private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1);
    private boolean valid = true;
    private Operation operation;
    /**
     * The visual component that displays this panel. If you need to access the
     * component from this class, just use getComponent().
     */
    private Component component;

    // Get the visual component for the panel. In this template, the component
    // is kept separate. This can be more efficient: if the wizard is created
    // but never displayed, or not all panels are displayed, it is better to
    // create only those which really need to be visible.
    @Override
    public Component getComponent() {
        if (component == null) {
            component = new OperationPanel();
            ((OperationPanel) component).addValidationListener(this);
        }
        return component;
    }

    /**
     * not used
     * @return 
     */
    @Override
    public HelpCtx getHelp() {
        return HelpCtx.DEFAULT_HELP;
    }

    /**
     * Will activate and deactivate the next button according to validation of the CropProtectionTasks
     * @return boolean valid
     */
    @Override
    public boolean isValid() {
        return valid;
    }

    /**
     * validate the Problems if there are any valid will be false 
     * @param prblms
     * @return always true 
     */
    @Override
    protected boolean validate(Problems prblms) {
        if (prblms.hasFatal()) {
            setValid(false);
        } else {
            setValid(true);
        }
        fireChangeEvent();
        return true;
    }

    private void setValid(boolean valid) {
        this.valid = valid;
    }

    /**
     * ads a ChangeListener
     * @param l ChangeListener to be added
     */
    @Override
    public final void addChangeListener(ChangeListener l) {
        synchronized (listeners) {
            listeners.add(l);
        }
    }

    /**
     * removes a ChangeListener
     * @param l ChangeListener to be removed
     */
    @Override
    public final void removeChangeListener(ChangeListener l) {
        synchronized (listeners) {
            listeners.remove(l);
        }
    }

    /**
     * fires a ChangeEvent on the registered ChangeListeners
     */
    protected final void fireChangeEvent() {
        Iterator<ChangeListener> it;
        synchronized (listeners) {
            it = new HashSet<ChangeListener>(listeners).iterator();
        }
        ChangeEvent ev = new ChangeEvent(this);
        while (it.hasNext()) {
            it.next().stateChanged(ev);
        }
    }

    // You can use a settings object to keep track of state. Normally the
    // settings object will be the WizardDescriptor, so you can use
    // WizardDescriptor.getProperty & putProperty to store information entered
    // by the user.
    @Override
    public void readSettings(Object settings) {
        List<CropProtectionTask> storedCropProtectionTasks = (List<CropProtectionTask>) ((WizardDescriptor) settings).getProperty(CROP_PROTECTION_TASK_PROPERTIES);
        // Retrieve selected cropprotections from the wizarddescriptor (Set in previous wizardpanel)
        //Clone the list otherwise the list in the wizard descriptor wil also be emptied
        List<CropProtection> cropProtections = new ArrayList<CropProtection>();
        cropProtections = (List<CropProtection>) ((ArrayList<CropProtection>) ((WizardDescriptor) settings).getProperty(CropProtectionController.CROP_PROTECTION)).clone();
        //List of cropProtectionTasks to remove from panel because they are no longer in cropProtections list
        List<CropProtectionTask> toBeRemovedCropProtectionTasks = new ArrayList<CropProtectionTask>();
        // Check if there are no stored cropProtectiontasks which are still selected
        if (storedCropProtectionTasks != null) {
            for (CropProtectionTask stored : storedCropProtectionTasks) {
                if (cropProtections.contains(stored.getCropProtection())) {
                    cropProtections.remove(stored.getCropProtection());
                    ((WizardDescriptor) settings).getProperty(CropProtectionController.CROP_PROTECTION);
                } else{
                    toBeRemovedCropProtectionTasks.add(stored);
                }
               
            }
        }
        //Remove unselected CropProtectionTasks from panel
        for (CropProtectionTask toBeRemoved : toBeRemovedCropProtectionTasks) {
            ((OperationPanel) getComponent()).removeCropProtectionTask(toBeRemoved);
        }

        if (operation == null) {
            ProductionUnit productionUnit = Utilities.actionsGlobalContext().lookup(ProductionUnit.class);
            operation = new Operation.Builder().setProductionUnit(productionUnit).build();
        }
        // Set selected cropprotections on panel
        for (CropProtection cropProtection : cropProtections) {
            CropProtectionTask cropProtectionTask = new CropProtectionTask.Builder().setCropProtection(cropProtection).setOperation(operation).build();
            ((OperationPanel) getComponent()).addCropProtectionTask(cropProtectionTask);
        }
    }

    /**
     * stores the selected PesticidePropertyRows
     * @param the WizardDescriptor 
     */
    @Override
    public void storeSettings(Object settings) {
        List<CropProtectionTask> cropProtectionTasks = ((OperationPanel) getComponent()).getCropProtectionTasks();
        ((WizardDescriptor) settings).putProperty(CROP_PROTECTION_TASK_PROPERTIES, cropProtectionTasks);
    }
}
